package com.bayesianWeka;

import weka.classifiers.AbstractClassifier;
import weka.core.Instance;
import weka.core.Instances;
import weka.core.Utils;

import java.util.Arrays;

/**
 * @Author: Decade
 * @Date: 2021/4/10 9:27
 */
public class NaiveBayes extends AbstractClassifier {

    /*类标签的个数*/
    private int m_NumClasses;

    /*实例的个数*/
//    private int m_NumInstances;

    /*属性的个数，在weka中，本值为预测属性和类属性之和*/
    private int m_NumAttributes;

    /*训练集类标签的索引*/
    private int m_ClassIndex;

    /*通用工具类*/
    private CommonUtils commonUtils;

    /**
     * 训练阶段，本阶段主要做两件事情：1. 变量的初始化 数组空间的申请 2. General版本模型分类器的构建
     * @param instances 测试集对象
     */
    @Override
    public void buildClassifier(Instances instances) throws Exception {
        //在NaiveBayes里，没有模型学习的过程，所以这个方法只用于做初始化
//        m_NumInstances = instances.numInstances();
        commonUtils = new CommonUtils(instances);
        m_NumClasses = commonUtils.getM_NumClasses();
        m_NumAttributes = commonUtils.getM_NumAttributes();
        m_ClassIndex = commonUtils.getM_ClassIndex();
    }

    /**
     * 分类/决策阶段，本阶段主要做两件事：
     * 1. 给定测试样本，计算联合概率，并返回归一化后的联合概率(即后验概率)，用于分类器做决策
     * 2. Local版本分类器的构建
     * @param instance 一个测试样本实例
     * @return 后验概率
     */
    public double[] distributionForInstance(Instance instance) throws Exception{
        double[] probs = new double[m_NumClasses];

        for (int y = 0; y < m_NumClasses; y++) {
            double p = commonUtils.P(y) * (Double.MAX_VALUE / 2);

            for (int x = 0; x < m_NumAttributes; x++) {
                if (x == m_ClassIndex)
                    continue;
                p *= commonUtils.P(instance,x,y);
//                System.out.print(p + "   ");
            }

            probs[y] = p;
        }
        Utils.normalize(probs);
//        System.out.println(Arrays.toString(probs));
        return probs;
    }

    /**
     * 主方法 用于运行分类器 runClassifier(new KDB(), args);语句中的KDB()要与分类器名字(即本java文件的主类名字)一一对应
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        runClassifier(new NaiveBayes(),args);
    }
}
